//+---------------------------------------------------------------------+
//				一般関数
//+---------------------------------------------------------------------+

double AdjustPoint(string Currency)//ポイント調整
{
	 long Symbol_Digits=SymbolInfoInteger(Currency,SYMBOL_DIGITS);
	 double Calculated_Point=0;
	 if (Symbol_Digits==2 || Symbol_Digits==3)
	 {
		 Calculated_Point=0.01;
	 }
	 else if (Symbol_Digits==4 || Symbol_Digits==5)
	 {
		 Calculated_Point=0.0001;
	 }
	 else if (Symbol_Digits==1)
	 {
		 Calculated_Point=0.1;
	 }
	 else if (Symbol_Digits==0)
	 {
		 Calculated_Point=1;
	 }
	 return(Calculated_Point);
}

int AdjustSlippage(string Currency,int Slippage_pips )//スリッページ調整
{
	 int Calculated_Slippage=0;
	 long Symbol_Digits=SymbolInfoInteger(Currency,SYMBOL_DIGITS);
	 if (Symbol_Digits==2 || Symbol_Digits==3)
	 {
		 Calculated_Slippage=Slippage_pips;
	 }
	 else if (Symbol_Digits==4 || Symbol_Digits==5)
	 {
		 Calculated_Slippage=Slippage_pips*10;
	 }
	 return(Calculated_Slippage); 
}

double AdjustValByPips(double BeforeAdjustVal)
{
	 double Num=0;
	 double ret=0;
	 Num=MathRound(   (BeforeAdjustVal-RangeMin) / (StepPips*AdjustPoint(Symbol()))   );
	 ret=RangeMin+(Num*  (StepPips*AdjustPoint( Symbol() )  )   );  
	 return (ret);
}
int LongPosition()//ロングポジション数を取得
{
	 int buys=0;
	 int total=PositionsTotal();
	 ulong ticket=0;
	 ulong PositionMagic=0;
	 long type;
	 string symbol;
	 for(int i=total-1;i>=0;i--)
	 {
		 ticket=PositionGetTicket(i); 
		 symbol=PositionGetString(POSITION_SYMBOL); 
		 PositionMagic=PositionGetInteger(POSITION_MAGIC);
		 type  =PositionGetInteger(POSITION_TYPE); 
		 if(symbol==_Symbol && PositionMagic==MAGIC && type==POSITION_TYPE_BUY )
		 {
			 buys++;
		 }
	 }
	 return(buys);
}

int ShortPosition()//ショートポジション数を取得
{
	 int sells=0;
	 int total=PositionsTotal();
	 ulong ticket=0;
	 ulong PositionMagic=0;
	 long type;
	 string symbol;
	 for(int i=total-1;i>=0;i--)
	 {
		 ticket=PositionGetTicket(i); 
		 symbol=PositionGetString(POSITION_SYMBOL); 
		 PositionMagic=PositionGetInteger(POSITION_MAGIC);
		 type  =PositionGetInteger(POSITION_TYPE); 
		 if(symbol==_Symbol && PositionMagic==MAGIC && type==POSITION_TYPE_SELL )
		 {
			 sells++;
		 }
	 }
	 return(sells);
}

int LongOrder()//ロング注文数を取得
{
	 int buys=0;
	 ulong order_ticket; 
	 for(int i=0;i<OrdersTotal();i++)
	 {
		 order_ticket=OrderGetTicket(i);
		 {
		 if(OrderGetInteger(ORDER_MAGIC)==MAGIC && (OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP)) buys++; 
		 }
	 }
	 return(buys);
}

int ShortOrder()//ショート注文数を取得
{
	 int sells=0;
	 ulong order_ticket; 
	 for(int i=0;i<OrdersTotal();i++)
	 {
		 order_ticket=OrderGetTicket(i);
		 {
		 if(OrderGetInteger(ORDER_MAGIC)==MAGIC && (OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP)) sells++; 
		 }
	 }
	 return(sells);
}

//+---------------------------------------------------------------------+
//				エグジット関連関数
//+---------------------------------------------------------------------+

//ポジションクローズ関数
void CloseOrder(int ClosePosition)
{
	 MqlTradeRequest request={0};
	 MqlTradeResult  result={0};
	 int total=PositionsTotal(); 
	 for(int i=total-1;i>=0;i--) 
	 {
		 //ポジション情報を取得 
		 ulong  position_ticket=PositionGetTicket(i); //ポジションチケット
		 string position_symbol=PositionGetString(POSITION_SYMBOL);  //シンボル 
		 ulong  magic=PositionGetInteger(POSITION_MAGIC); //ポジションのMagicNumber
		 double volume=PositionGetDouble(POSITION_VOLUME); // ポジションボリューム
		 ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);   // ポジションタイプ
		 double profit=PositionGetDouble(POSITION_PROFIT);
		 if(magic==MAGIC && position_symbol==_Symbol )
		 {
		 //注文のパラメータ設定
		 request.action   =TRADE_ACTION_DEAL;   
		 request.position =position_ticket;   
		 request.symbol   =position_symbol; 
		 request.volume   =volume;  
		 request.deviation=50;
		 request.magic    =MAGIC; 
		 if(type==POSITION_TYPE_BUY && (ClosePosition==1||ClosePosition==0) )
		 {
		 request.price=SymbolInfoDouble(position_symbol,SYMBOL_BID);
		 request.type =ORDER_TYPE_SELL;
		 bool ret=OrderSend(request,result);
		 }
		 else if(type==POSITION_TYPE_SELL && (ClosePosition==-1 || ClosePosition==0 ))
		 {
		 request.price=SymbolInfoDouble(position_symbol,SYMBOL_ASK);
		 request.type =ORDER_TYPE_BUY;
		 request.type_filling=ORDER_FILLING_FOK;  
		 request.comment="half";  
		 bool ret=OrderSend(request,result);
		 }
		 }
	 }
}


//オーダーキャンセル関数
void CancelOrder(int CancelPosition) 
{
	 MqlTradeRequest request={0};
	 MqlTradeResult  result={0};
	 int ttl=OrdersTotal();
	 for(int i=ttl-1; i>=0; i--)
	 {
		 ZeroMemory(request);
		 ZeroMemory(result);
		 ulong  order_ticket=OrderGetTicket(i);
		 ulong  magic=OrderGetInteger(ORDER_MAGIC);
		 string symbol=OrderGetString(ORDER_SYMBOL); 
		 long   type= OrderGetInteger(ORDER_TYPE);
		 
		 if(magic==MAGIC && symbol==_Symbol && CancelPosition==1 && (type==ORDER_TYPE_BUY_LIMIT || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_STOP_LIMIT  ) )  
		 {
			 request.action=TRADE_ACTION_REMOVE;
			 request.order = order_ticket;  
			 bool rtn=OrderSend(request,result);
		 }
		 if(magic==MAGIC && symbol==_Symbol && CancelPosition==-1 && (type==ORDER_TYPE_SELL_LIMIT || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_STOP_LIMIT  ) )
		 {
			 request.action=TRADE_ACTION_REMOVE;
			 request.order = order_ticket;  
		 request.comment="half";  
			 bool rtn=OrderSend(request,result);
		 }
	 }
}

//+---------------------------------------------------------------------+
//				　インジケーター
//+---------------------------------------------------------------------+

//+---------------------------------------------------------------------+
//				イニシャル処理
//+---------------------------------------------------------------------+
void OnInit()
{

}
//+---------------------------------------------------------------------+
//				ティック毎の処理
//+---------------------------------------------------------------------+
void OnTick()
{
 
	 double Bid, Ask;
	 MqlTick tick;
	 SymbolInfoTick(_Symbol, tick);
	 Bid = tick.bid;
	 Ask = tick.ask;
 
	 
	 // ニューバーの発生直後以外は取引しない 
	 datetime TimeArray[1];
	 CopyTime(_Symbol, _Period, 0, 1, TimeArray);
	 if(TimeArray[0] == Time) return;
	 Time = TimeArray[0];
	 
	 int EntryBuy=0;
	 int EntrySell=0;
	 int ExitBuy=0;
	 int ExitSell=0;
	 
	 
	 int LongNum=LongPosition();
	 int ShortNum=ShortPosition();
	 int LongOrderNum=LongOrder();
	 int ShortOrderNum=ShortOrder();
	 
	 double rangeHalf=(RangeMax+RangeMin)*0.5;
	 double lastValue=iClose(NULL,0,1);
	 if(Direction==2)
	 {
		 if(lastValue>rangeHalf) 
		 { 
		 EntrySell=1; 
		 } 
		 else 
		 { 
		 EntryBuy=1; 
		 } 
	 }
	 
	 
	 //クローズロジックは選択されていません
	 
	 //クローズ判定
	 //買いのクローズロジックは選択されていません
	 //売りのクローズロジックは選択されていません

	 int Strtagy=0;
	 if (EntryBuy==1) Strtagy=1 ; 
	 if (EntrySell==1) Strtagy=-1 ; 

	 //方向が違う場合にはポジション決済 
	 if (LongNum!=0 && (EntrySell==1 || Strtagy==-99  || Direction==-99 ) )  
	 { 
		 CloseOrder(1);
		 LongNum=LongPosition();
	 } 

	 if (ShortNum!=0 && ( EntryBuy==1 || Strtagy==-99 || Direction==-99 ) )  
	 { 
		 CloseOrder(-1);
		 ShortNum=ShortPosition();
	 } 


	 //エントリ方向又はフィルターとトラップの向きが違う場合は全注文キャンセル 
	 if (LongOrderNum!=0 && EntrySell==1 ) 
	 { 
		 CancelOrder(1);
		 LongOrderNum=0;
	 } 

	 if (ShortOrderNum!=0 && EntryBuy==1 )  
	 { 
		 CancelOrder(-1);
		 ShortOrderNum=0;
	 } 

	 if (LongNum!=0 && Strtagy==-1)  
	 { 
		 CancelOrder(1);
		 LongOrderNum=0;
	 } 

	 if (ShortNum!=0 && Strtagy==1)  
	 { 
		 CancelOrder(-1);
		 ShortOrderNum=0;
	 } 

	 if (Strtagy==0 && (LongOrderNum!=0 || ShortOrderNum!=0)  ) 
	 { 
		 CancelOrder(1);
		 LongOrderNum=0;
		 CancelOrder(-1);
		 ShortOrderNum=0;
	 } 


	 //注文がレンジ範囲外の場合にはトラップを範囲外のトラップをキャンセル 
	 double OrderRangeMin; 
	 double OrderRangeMax; 
	 double CurrentPrice=0; 
	 if (EntryBuy==1) CurrentPrice=Bid; 
	 if (EntrySell==1) CurrentPrice=Ask; 
	 OrderRangeMin=CurrentPrice-(OrderRange*0.5)*AdjustPoint(_Symbol); 
	 OrderRangeMax=CurrentPrice+(OrderRange*0.5)*AdjustPoint(_Symbol); 

	 MqlTradeRequest request={0};
	 MqlTradeResult  result={0};
	 int ttl=OrdersTotal();
	 for(int i=ttl-1; i>0; i--)
	 {
		 ZeroMemory(request);
		 ZeroMemory(result);
		 ulong  order_ticket=OrderGetTicket(i);
		 ulong  magic=OrderGetInteger(ORDER_MAGIC);
		 string symbol=OrderGetString(ORDER_SYMBOL); 
		 double openPrice=OrderGetDouble(ORDER_PRICE_OPEN);
	 
		 if(magic==MAGIC && symbol==_Symbol && ( (RangeMin>openPrice || openPrice>RangeMax ) || (OrderRangeMin>openPrice || openPrice>OrderRangeMax ) ) ) 
		 {
			 request.action=TRADE_ACTION_REMOVE; 
			 request.symbol=_Symbol;  
			 request.magic=magic;  
			 request.order=order_ticket;
			 request.comment="half";  
			 bool ret=OrderSend(request,result);
		 }
	 }


	 //ロットサイズ調整 
		 Lots=BaseLots;//固定ロット
	 // 
	 //トラップを張る 
	 // 
	 int SLP=AdjustSlippage(Symbol(),Slippage ); 
	 double OrderPrice; 
	 double TP=0; 
	 double SL=0; 
	 int size=0; 
	 double rangeArray[1000]; 
	 double positionArray[1000]; 
	 ArrayInitialize(rangeArray,0); 
	 ArrayInitialize(positionArray,0); 

	 //オーダー範囲内の金額を配列に記録 
	 for(int i=0; RangeMax>RangeMin+((StepPips*i)*AdjustPoint(Symbol())); i++ ) 
	 { 
		 OrderPrice=RangeMin+((StepPips*i)*AdjustPoint(Symbol())); 
		 if (OrderRangeMin<OrderPrice && OrderPrice<OrderRangeMax )  
		 { 
			 rangeArray[i]=OrderPrice; 
		 } 
	 } 
	 //注文ずみを配列に記録 
	 ttl=OrdersTotal();
	 for(int i=0; i<=ttl-1; i++)
	 {
		 ulong  order_ticket=OrderGetTicket(i);
		 bool   ret=OrderSelect(order_ticket);
		 ulong  magic=OrderGetInteger(ORDER_MAGIC);
		 string symbol=OrderGetString(ORDER_SYMBOL); 
		 double openPrice=OrderGetDouble(ORDER_PRICE_OPEN);
	 
		 if(magic==MAGIC && symbol==_Symbol) 
		 {
			 positionArray[i]=AdjustValByPips(openPrice);
		 }
	 }
	 
	 ttl=PositionsTotal();
	 ulong ticket=0;
	 ulong PositionMagic=0;
	 string symbol;
	 double openPrice;
	 for(int i=0; i<=ttl-1; i++)
	 {
		 ticket=PositionGetTicket(i); 
		 bool ret=PositionSelectByTicket(ticket);
		 symbol=PositionGetString(POSITION_SYMBOL); 
		 PositionMagic=PositionGetInteger(POSITION_MAGIC);
		 openPrice  =PositionGetDouble(POSITION_PRICE_OPEN); 
		 if(PositionMagic==MAGIC && symbol==_Symbol) 
		 {
			 positionArray[i+OrdersTotal()]=AdjustValByPips(openPrice);
		 }
	 }
	 
	 //オーダー範囲内にあるのにpositionがない場合に注文追加 
	 double search; 
	 int ret; 
	 for(int i=0;i<ArraySize(rangeArray);i++) 
	 { 
		 search=AdjustValByPips(rangeArray[i]); 
		 ret=0; 
		 for(int j=0;j<ArraySize(positionArray);j++) 
		 { 
			 if (positionArray[j]==search && ret==0) 
			 { 
				 ret=1; 
				 break; 
			 } 
		 } 
		  
		 if (ret==0) 
		 { 
			 OrderPrice=search; 
			 if (EntryBuy==1 && Strtagy==1 ) 
			 { 
				 TP=OrderPrice+(takeprofit*AdjustPoint(Symbol())); 
				 if(stoploss!=0) SL=OrderPrice-(stoploss*AdjustPoint(Symbol())); 
				 if (OrderPrice<Bid && OrderPrice<=RangeMax && OrderPrice>=RangeMin ) 
				 { 
					 //指値 
					 ZeroMemory(request);
					 ZeroMemory(result);
					 request.action=TRADE_ACTION_PENDING; 
					 request.symbol=_Symbol;  
					 request.magic=MAGIC;  
					 request.volume=Lots;  
					 request.price=OrderPrice;  
					 request.type=ORDER_TYPE_BUY_LIMIT;  
					 request.sl=SL;  
					 request.tp=TP;  
				 request.type_filling=ORDER_FILLING_FOK;  
					 request.comment="half";  
					 ret=OrderSend(request,result);
				 } 
				 else if (OrderPrice<=RangeMax && OrderPrice>=RangeMin) 
				 { 
					 //逆指値 
					 ZeroMemory(request);
					 ZeroMemory(result);
					 request.action=TRADE_ACTION_PENDING; 
					 request.symbol=_Symbol;  
					 request.magic=MAGIC;  
					 request.volume=Lots;  
					 request.price=OrderPrice;  
					 request.type=ORDER_TYPE_BUY_STOP;  
					 request.sl=SL;  
					 request.tp=TP;  
				 request.type_filling=ORDER_FILLING_FOK;  
					 request.comment="half";  
					 ret=OrderSend(request,result);
				 } 
			 } 
			  
			 if (EntrySell==1 && Strtagy==-1 ) 
			 { 
				 TP=OrderPrice-(takeprofit*AdjustPoint(Symbol())); 
				 if(stoploss!=0) SL=OrderPrice+(stoploss*AdjustPoint(Symbol())); 
				 if (OrderPrice>Ask && OrderPrice<=RangeMax && OrderPrice>=RangeMin ) 
				 { 
					 //指値 
					 ZeroMemory(request);
					 ZeroMemory(result);
					 request.action=TRADE_ACTION_PENDING; 
					 request.symbol=_Symbol;  
					 request.magic=MAGIC;  
					 request.volume=Lots;  
					 request.price=OrderPrice;  
					 request.type=ORDER_TYPE_SELL_LIMIT;  
					 request.sl=SL;  
					 request.tp=TP;  
				 request.type_filling=ORDER_FILLING_FOK;  
					 request.comment="half";  
					 ret=OrderSend(request,result);
				 } 
				 else if (OrderPrice<=RangeMax && OrderPrice>=RangeMin)
				 { 
					 //逆指 
					 ZeroMemory(request);
					 ZeroMemory(result);
					 request.action=TRADE_ACTION_PENDING; 
					 request.symbol=_Symbol;  
					 request.magic=MAGIC;  
					 request.volume=Lots;  
					 request.price=OrderPrice;  
					 request.type=ORDER_TYPE_SELL_STOP;  
					 request.sl=SL;  
					 request.tp=TP;  
				 request.type_filling=ORDER_FILLING_FOK;  
					 request.comment="half";  
					 ret=OrderSend(request,result);
				 } 
			 } 
		 } 
	 }
}
